package com.test.jbpm.dao.impl;


import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessDefinitionQuery;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.RepositoryService;
import org.jbpm.api.TaskService;
import org.jbpm.api.task.Task;
import org.jbpm.pvm.internal.model.ExecutionImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import com.test.jbpm.Pager;
import com.test.jbpm.PagerContext;
import com.test.jbpm.dao.TroubleTicketDao;
import com.test.jbpm.domain.TroubleTicket;


@Repository
public class TroubleTicketDaoImpl extends BaseDao implements TroubleTicketDao {

	private RepositoryService repositoryService;
	
	private ExecutionService executionService;
	
	private TaskService taskService;
	
	@Autowired
	public void setRepositoryService(RepositoryService repositoryService) {
		this.repositoryService = repositoryService;
	}
	
	@Autowired
	public void setExecutionService(ExecutionService executionService) {
		this.executionService = executionService;
	}
	
	@Autowired
	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public void addOrUpdate(TroubleTicket troubleTicket) {
		getHibernateTemplate().saveOrUpdate(troubleTicket);
	}

	public void del(Integer troubleTicketId) {
		getHibernateTemplate().delete(
			getHibernateTemplate().load(TroubleTicket.class, troubleTicketId)	
		);
	}

	@SuppressWarnings("unchecked")
	public Pager<TroubleTicket> findMyTroubleTicketList(Integer creatorId) {
		String hql = "from TroubleTicket tt where tt.creator.id=? order by tt.happenTime desc";
		return findData(hql, creatorId);
	}

	public TroubleTicket findTroubleTicketById(Integer troubleTicketId) {
		return (TroubleTicket) getHibernateTemplate().load(TroubleTicket.class, troubleTicketId);
	}

	/* (non-Javadoc)
	 * @see com.bwie.pmes.dao.TroubleTicketDao#dispatch(java.lang.Integer)
	 */
	public void dispatch(Integer troublelTicketId) {
		//取得最新版本的流程
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionName("TroubleTicket")
				.orderDesc(ProcessDefinitionQuery.PROPERTY_VERSION)
				.page(0, 1)
				.uniqueResult();
				
		//根据流程定义，启动流程
		ProcessInstance processInstance = executionService.startProcessInstanceById(processDefinition.getId());
		
		//取得当前执行Execution
		ExecutionImpl executionImpl = (ExecutionImpl)processInstance;
		
		//根据id取得请假单
		TroubleTicket troubleTicket= (TroubleTicket)getHibernateTemplate().load(TroubleTicket.class, troublelTicketId);
		//设置请假单的状态为当前流程所处于的活动名称
		troubleTicket.setStatus(executionImpl.getActivityName());
		
		//将请假单信息设置到流程变量中
		Map<String, Object> variables = new HashMap<String, Object>();
		variables.put("troubleTicketId", troubleTicket.getId());
		variables.put("level", troubleTicket.getLevel());
		//processInstance和executionImpl的id是一样的,executionImpl实现了processInstance
		executionService.setVariables(executionImpl.getId(), variables);
	}

	public Pager<TroubleTicket> findApprovingTroubleTicketList(
			Integer approverId) {
		//访问JBPM4取得待审任务
		List<Task> taskList = taskService.findPersonalTasks(String.valueOf(approverId));
		//根据待审任务，取得每个任务对应的流程变量的值（请假单id）
		//将请假单号统一放到一个集合中
		final List<Integer> troubleTicketList = new ArrayList<Integer>();
		for (Task task : taskList) {
			Integer troubleTicketId = (Integer)taskService.getVariable(task.getId(), "troubleTicketId");
			troubleTicketList.add(troubleTicketId);
		}
		//根据取得的请假单号，查询请假单
		// from TroubleTicket tt where tt.id in(?,?,?,?) order by tt.happenTime desc
		StringBuilder sbHql = new StringBuilder();
		if (troubleTicketList.size() != 0) {
			sbHql.append("from TroubleTicket tt where tt.id in(");
			for (int i=0; i<troubleTicketList.size(); i++) {
				sbHql.append("?");
				if (i<(taskList.size() - 1)) {
					sbHql.append(",");
				}
			}
			sbHql.append(") ");
			sbHql.append(" order by tt.happenTime desc");
			return findData(sbHql.toString(), troubleTicketList);
	    }else {
	    	return new Pager<TroubleTicket>();
	    }
//		getHibernateTemplate().executeFind(new HibernateCallback() {
//			@Override
//			public Object doInHibernate(Session session) throws HibernateException,
//					SQLException {
//				return session.createQuery("from TroubleTicket tt where tt.id in(:troubleTicketIds)")
//							.setParameterList("troubleTicketIds", troubleTicketIList)
//							.setFirstResult(PagerContext.getOffset())
//							.setMaxResults(PagerContext.getPageSize())
//							.list();
//			}
//		});
	}

	public void completeTask(Integer troubleTicketId, Integer approverId) {
		//取得审批人的任务
		List<Task> taskList = taskService.findPersonalTasks(String.valueOf(approverId));
		
		//当前请假单对应的task
		Task currentTask = null;
		for (Task task : taskList) {
			if (((Integer)taskService.getVariable(task.getId(), "troubleTicketId")).intValue() == troubleTicketId) {
				currentTask = task;
				break;
			}
		}
		if (currentTask != null) {
			//完成任务
			taskService.completeTask(currentTask.getId());
		}
		//取得请假单
		TroubleTicket troubleTicket = (TroubleTicket)getHibernateTemplate().load(TroubleTicket.class, troubleTicketId);
		
		//取得当前任务对应的流程实例
		ProcessInstance processInstance = executionService.findProcessInstanceById(currentTask.getExecutionId());
		//如果流程没有结束
		if(processInstance != null) {
			//取得当前执行Execution
			ExecutionImpl executionImpl = (ExecutionImpl)processInstance;
			//设置请假单的状态为活动名称
			troubleTicket.setStatus(executionImpl.getActivityName());
		}else {
			//设置请假单的状态为完成
			troubleTicket.setStatus(TroubleTicket.END);
		}
	}
	
	public void completeBackTask(Integer troubleTicketId, Integer approverId) {
		//取得审批人的任务
		List<Task> taskList = taskService.findPersonalTasks(String.valueOf(approverId));
		
		//当前请假单对应的task
		Task currentTask = null;
		for (Task task : taskList) {
			if (((Integer)taskService.getVariable(task.getId(), "troubleTicketId")).intValue() == troubleTicketId) {
				currentTask = task;
				break;
			}
		}
		if (currentTask != null) {
			//完成任务
			taskService.completeTask(currentTask.getId());
		}
		//取得请假单
		TroubleTicket troubleTicket = (TroubleTicket)getHibernateTemplate().load(TroubleTicket.class, troubleTicketId);
		troubleTicket.setStatus(TroubleTicket.END);
		//取得当前任务对应的流程实例
//		ProcessInstance processInstance = executionService.findProcessInstanceById(currentTask.getExecutionId());
//		//如果流程没有结束
//		if(processInstance != null) {
//			//取得当前执行Execution
//			ExecutionImpl executionImpl = (ExecutionImpl)processInstance;
//			//设置请假单的状态为活动名称
//			troubleTicket.setStatus(executionImpl.getActivityName());
//		}else {
//			//设置请假单的状态为完成
//			troubleTicket.setStatus(TroubleTicket.END);
//		}
	}

	@SuppressWarnings("unchecked")
	public Pager<TroubleTicket> findApprovedTroubleTicketList(final Integer approverId) {
		List<TroubleTicket> troubleTicketList = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				return session.createQuery("select distinct ai.troubleTicket from ApproveInfo ai where ai.approver.id=? order by ai.approveTime desc")
							.setParameter(0, approverId)
							.setFirstResult(PagerContext.getOffset())
							.setMaxResults(PagerContext.getPageSize())
							.list();
			}
		});
		
		Long total = (Long)getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				return session.createQuery("select count(distinct ai.troubleTicket) from ApproveInfo ai where ai.approver.id=?")
							.setParameter(0, approverId)
							.uniqueResult();
			}
		});
		Pager<TroubleTicket> pager = new Pager<TroubleTicket>();
		pager.setData(troubleTicketList);
		pager.setTotal(total.intValue());
		return pager;
	}
}
